/*****************************************************************************/ /*!
* file  : systask.c
* creat : apleilx
* note :  除初始化外，禁止该任务及其子程序使用含有阻塞的功能，包括数据存储，USB操作等等
* data  : 2019/07/02
*******************************************************************************/
#include "common.h"

#include "bsp_api.h"
#include "bsp_spi_nor.h"
#include "nor_cmd.h"

#include "lut\nand_lut.h"
#include "nand_w25n.h"

#include "swap.h"

#include "fat_file_opt.h"
#include "simp_fat_update.h"

/*****************************************************************************
* @brief   const define
*****************************************************************************/
#define NAND_BLOCK_SITE_FILE 16
#define SIMP_TAB_ADDR_BASE 0x400000
/*****************************************************************************
* @brief   function
*****************************************************************************/
uint8_t nand_get_blk_dat(nand_lut_type *lut, uint32_t addr_offset, uint8_t *pdat, uint16_t len);

/*****************************************************************************
* @brief   extern var
*****************************************************************************/
extern nand_lut_type nand_dev;

/*****************************************************************************
* @brief   simp_fat_tab_erase.
* @param   none
* @return  none
*****************************************************************************/
void simp_fat_tab_erase(void)
{
	switch (efat.fsel)
	{
	case FSEL_MBED_H:
		nor_sector_erase(SIMP_TAB_ADDR_BASE);
		nor_sector_erase(SIMP_TAB_ADDR_BASE + 0x1000);
		nor_sector_erase(SIMP_TAB_ADDR_BASE + 0x2000);
		nor_sector_erase(SIMP_TAB_ADDR_BASE + 0x3000);
		break;
	case FSEL_GUI_PACKAGE:
		break;
	case FSEL_SYS_PAR:
		break;
	default:
		break;
	}
}

/*****************************************************************************
* @brief   simp_fat_tab_write.
* @param   none
* @return  none
*****************************************************************************/
void simp_fat_tab_write(uint32_t addr_offset, uint8_t *buff, uint32_t len)
{
	switch (efat.fsel)
	{
	case FSEL_MBED_H:
		nor_write_multi(SIMP_TAB_ADDR_BASE + addr_offset, len, buff);
		break;
	case FSEL_GUI_PACKAGE:
		break;
	case FSEL_SYS_PAR:
		break;
	default:
		break;
	}
}

/*****************************************************************************
* @brief   simp_fat_tab_save.
* @param   none
* @return  none
*****************************************************************************/
void simp_fat_tab_save(void)
{
	switch (efat.fsel)
	{
	case FSEL_MBED_H:
		break;
	case FSEL_GUI_PACKAGE:
		break;
	case FSEL_SYS_PAR:
		break;
	default:
		break;
	}
}

/*****************************************************************************
* @brief   simp_fat_main_write_start.
* @param   none
* @return  none
*****************************************************************************/
void simp_fat_main_write_start(void)
{
	uint8_t falsh_st;

	switch (efat.fsel)
	{
	case FSEL_MBED_H:
	{
		// flash write enable
		spi_nand_write_enable();
		falsh_st = spi_nand_featute_get(NAND_FEATURE_1_PROTECT); //测试读取的默认值是0x7C
		flash_dbg_print("read nand reg1 = 0x%02X\n", falsh_st);
		if (falsh_st != 0)
		{
			flash_dbg_print("nand set reg1 to 0x00\n");
			spi_nand_write_enable();
			spi_nand_featute_set(NAND_FEATURE_1_PROTECT, 0xFF, 0);
			falsh_st = spi_nand_featute_get(NAND_FEATURE_1_PROTECT);
			flash_dbg_print("read nand reg1 = 0x%02X\n", falsh_st);
		}
		break;
	}
	case FSEL_GUI_PACKAGE:
		break;
	case FSEL_SYS_PAR:
		break;
	default:
		break;
	}
}

/*****************************************************************************
* @brief   simp_fat_main_write_start.
* @param   none
* @return  none
*****************************************************************************/
void simp_fat_main_write_end(void)
{
	switch (efat.fsel)
	{
	case FSEL_MBED_H:
		// flash write disable
		spi_nand_write_disable();
		break;
	case FSEL_GUI_PACKAGE:
		break;
	case FSEL_SYS_PAR:
		break;
	default:
		break;
	}
}

/*****************************************************************************
* @brief   simp_fat_main_write_start.
* @param   none
* @return  none
*****************************************************************************/
void simp_fat_main_write(uint32_t block)
{
	switch (efat.fsel)
	{
	case FSEL_MBED_H:
		nand_dev.api.block_write(block + NAND_BLOCK_SITE_FILE, nand_get_blk_dat);
		break;
	case FSEL_GUI_PACKAGE:
		break;
	case FSEL_SYS_PAR:
		break;
	default:
		break;
	}
}

/*****************************************************************************
* @brief   nand_get_blk_dat
* @param   addr pdat len
* @return  non
*****************************************************************************/
uint8_t nand_get_blk_dat(nand_lut_type *lut, uint32_t addr_offset, uint8_t *pdat, uint16_t len)
{
	UINT len_back;
	int b_hash_en = 0;

	int fil_site = efat.wr_fil_block * efat.wr_block_size + addr_offset;
	if (efat.wr_hash_site < fil_site)
	{
		efat.wr_hash_site = fil_site;
		b_hash_en = 1;
	}

	// 读取文件
	if (fil_site < efat.main_len)
	{
		// 文件定位-仅在回写时重新定位
		if (fil_site < efat.wr_site_old)
		{
			fat_fil_seek(efat.fil, fil_site + efat.main_site);
			flash_dbg_print("nand block write reseek @ %04X, offset : %d", efat.wr_fil_block, addr_offset);
		}

		// aes mode
		if (efat.main_aes_mode == 0x55)
		{
			int site, len_rd;

			if (len + fil_site <= efat.main_len)
			{
				len_rd = len;
			}
			else
			{
				len_rd = efat.main_len - fil_site;
			}

			efat.fst = fat_fil_read(efat.fil, efat.buff, len_rd, &len_back);

			// decode
			for (site = 0; site < len_back; site += 16)
			{
				mbedtls_aes_crypt_ecb(efat.aes_obj, MBEDTLS_AES_DECRYPT, &efat.buff[site], &(pdat[site]));
				// hash cal
				if (b_hash_en)
				{
					if (efat.sha_en)
						mbedtls_sha256_update(efat.sha_obj, &pdat[site], 16);
					if (efat.md5_en)
						mbedtls_md5_update(efat.md5_obj, &pdat[site], 16);
				}
			}
		}
		// nor mode
		else
		{
			// read data
			efat.fst = fat_fil_read(efat.fil, pdat, len, &len_back);
			//hash cal
			if (b_hash_en)
			{
				if (efat.sha_en)
					mbedtls_sha256_update(efat.sha_obj, pdat, len_back);
				if (efat.md5_en)
					mbedtls_md5_update(efat.md5_obj, pdat, len_back);
			}
		}
		// 尾部补充 FF
		if (len_back < len)
		{
			set_u8(&pdat[len_back], 0xFF, len - len_back);
		}

		efat.wr_site_old = fil_site;
	}
	else
	{
		set_u8(pdat, 0xFF, len);
	}

	return 0;
}
